package org.sjs.dreamfly.widget

import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.exoplayer2.ui.StyledPlayerView
import org.sjs.dreamfly.R
import org.sjs.dreamfly.common.base.BaseViewHolder
import org.sjs.dreamfly.common.base.Listener
import org.sjs.dreamfly.common.base.ListenerOwner
import org.sjs.dreamfly.model.VideoInfo
import org.sjs.dreamfly.player.IPlayerDataProvider
import java.lang.ref.WeakReference
import kotlin.math.ceil
import kotlin.math.min

class PlayerView : StyledPlayerView, LockContainer.OnTouchListener, ListenerOwner<PlayerView.ActionListener> {

    interface ActionListener: Listener {
        override fun notify(vararg params: Any?) {
            val list = params[0] as Array<*>
            val method = list.firstOrNull() as? String
            when(method) {
                "onVideoItemClicked" -> onVideoItemClick(list[1] as Int)
                "onBackButtonClick" -> onBackButtonClick()
            }
        }
        fun onBackButtonClick()
        fun onVideoItemClick(index: Int) {}
    }

    constructor(context: Context) : this(context, null, 0)
    constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        initialize()
    }

    override val listeners =  mutableListOf<WeakReference<ActionListener>>()
    private var screenLocked = false
    private lateinit var titleBar: TitleBar
    private lateinit var lockContainer: LockContainer
    private lateinit var btnScreenLock: ImageView
    private lateinit var btnPlayList: View
    private lateinit var playListContainer: View
    private lateinit var playListView: RecyclerView
    private var index = 0
    private var useLockBtn: Boolean = true
    private var usePlayListBtn: Boolean = true
    private var viewModel: IPlayerDataProvider? = null

    private fun initialize() {
        val view = LayoutInflater.from(context).inflate(R.layout.widget_player_view_overlay, this.overlayFrameLayout)
        titleBar = view.findViewById(R.id.title_bar)
        lockContainer = view.findViewById(R.id.lock_container)
        btnScreenLock = view.findViewById(R.id.btn_screen_lock)
        btnPlayList = view.findViewById(R.id.btn_play_list)
        playListView = view.findViewById(R.id.play_list_view)
        playListContainer = view.findViewById(R.id.play_list_container)
        initViews()
    }

    private fun initViews() {
        overlayFrameLayout?.bringToFront()
        updateByOrientation(null)
        val activity = context as FragmentActivity
        titleBar.setStyle(true)
        titleBar.setOnBackListener(object : TitleBar.OnActionListener {
            override fun onBackButtonClick() {
                notifyListeners("onBackButtonClick")
            }
        })
        this.setControllerOnFullScreenModeChangedListener {
            if (activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
            } else {
                activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            }
        }
        lockContainer.addListener(this)
        this.setControllerVisibilityListener {
            titleBar.visibility = it
            updateScreenLockBtnVisible(it)
            updatePlaylistBtnVisible(it)
            updatePlayListVisible(it)
        }
        btnScreenLock.setOnClickListener { updateScreenLockState() }
        btnPlayList.setOnClickListener { updatePlayListVisible() }
        playListView.adapter = object : RecyclerView.Adapter<VH>() {
            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
                return VH(LayoutInflater.from(context)
                    .inflate(R.layout.item_play_list, null), { return@VH index }) { pos ->
                    notifyListeners("onVideoItemClicked", pos)
                }
            }

            override fun onBindViewHolder(holder: VH, position: Int) {
                viewModel?.getVideoList()?.get(position)?.let {
                    holder.bind(it, position)
                }
            }

            override fun getItemCount(): Int {
                return viewModel?.getVideoList()?.size?:0
            }
        }
        var spanCount = 3
        val size = viewModel?.getVideoList()?.size?:0
        if (size > 0) {
            spanCount = min(ceil(size / 8.0).toInt(), 5)
        }
        playListView.layoutManager = GridLayoutManager(context, spanCount)
    }

    override fun onConfigurationChanged(newConfig: Configuration?) {
        super.onConfigurationChanged(newConfig)
        updateByOrientation(newConfig?.orientation)
    }

    private fun updateByOrientation(orientation: Int?) {
        var orien = orientation
        if (orien == null) {
            orien = (context as Activity).requestedOrientation
        }
        if (orien == Configuration.ORIENTATION_LANDSCAPE) {
            useLockBtn = true
            usePlayListBtn = true
        } else {
            useLockBtn = false
            usePlayListBtn = false
            updateScreenLockBtnVisible()
            updatePlayListVisible()
            updatePlaylistBtnVisible()
        }
    }

    override fun onTouch(view: LockContainer, event: MotionEvent) {
        updateScreenLockBtnVisible(if (btnScreenLock.visibility == View.VISIBLE) View.GONE else View.VISIBLE)
    }

    private fun updatePlaylistBtnVisible(visibility: Int? = null) {
        if (!usePlayListBtn) {
            btnPlayList.visibility = View.GONE
            return
        }
        if ((viewModel?.getVideoList()?.size ?: 0) <= 1) {
            playListContainer.visibility = View.GONE
            return
        }
        visibility?.let { btnPlayList.visibility = it }
    }

    private fun updateScreenLockBtnVisible(visibility: Int? = null) {
        if (!useLockBtn) {
            btnScreenLock.visibility = View.GONE
            return
        }
        visibility?.let { btnScreenLock.visibility = it }

    }

    private fun updateScreenLockState() {
        screenLocked = !screenLocked
        btnScreenLock.setImageResource(if (screenLocked) R.mipmap.icon_lock else R.mipmap.icon_unlock)
        if (screenLocked) lockContainer.lock() else lockContainer.unLock()
        hideController()
    }

    fun updateTitle() {
        if ((viewModel?.getVideoList()?.size ?: 0) > 1) {
            titleBar.setTitle("${viewModel?.getVideoList()?.get(index)?.parent?.name} 第${index+1}集")
        } else {
            titleBar.setTitle("${viewModel?.getVideoList()?.get(index)?.parent?.name
                ?: viewModel?.getVideoList()?.get(index)?.title}")
        }
    }

    fun setDataProvider(provider: IPlayerDataProvider) {
        viewModel = provider
    }

    fun getIndex(): Int {
        return index
    }

    private fun updatePlayListVisible(visibility: Int? = null) {
        if (!usePlayListBtn) {
            playListContainer.visibility = View.GONE
            return
        }
        if ((viewModel?.getVideoList()?.size ?: 0) <= 1) {
            playListContainer.visibility = View.GONE
            return
        }
        if (visibility == null) {
            if (playListContainer.visibility == View.GONE) playListContainer.visibility = View.VISIBLE else playListContainer.visibility = View.GONE
        } else {
            if (visibility == View.GONE && playListContainer.visibility == View.VISIBLE) playListContainer.visibility = View.GONE
        }
    }

    fun updatePlayList(index: Int) {
        val oldIndex = this.index
        this.index = index
        playListView.adapter?.notifyItemChanged(oldIndex)
        playListView.adapter?.notifyItemChanged(index)
        updateTitle()
    }

    class VH(itemView: View, val current: ()->Int, val notify: (position: Int)->Unit) : BaseViewHolder<VideoInfo>(itemView) {
        override fun bind(data: VideoInfo, position: Int) {
            itemView.findViewById<TextView>(R.id.video_name).let {
                it.text = data.title
                it.isEnabled = current() != position
                if (it.isEnabled) {
                    it.setBackgroundResource(R.color.black)
                } else {
                    it.setBackgroundResource(R.color.primary)
                }
                it.setOnClickListener {
                    notify(position)
                }
            }
        }
    }
}